package com.mzj.saas.mservice.contract.service;

import com.alibaba.fastjson.JSON;
import com.itextpdf.text.pdf.BaseFont;
import com.mzj.saas.commons.DateUtils;
import com.mzj.saas.commons.DownloadUtil;
import com.mzj.saas.commons.ResultBean;
import com.mzj.saas.commons.enums.BacklogItemTypeEnum;
import com.mzj.saas.commons.enums.ContractStatusEnum;
import com.mzj.saas.commons.enums.OSSUploadFileTypeEnum;
import com.mzj.saas.commons.pdf.HtmlToPdfUtils;
import com.mzj.saas.commons.pdf.JavaToPdfHtmlFreeMarker;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.config.oss.OssConfig;
import com.mzj.saas.mservice.area.entity.Area;
import com.mzj.saas.mservice.area.repository.AreaRepository;
import com.mzj.saas.mservice.backlog.entity.BacklogItem;
import com.mzj.saas.mservice.backlog.entity.BacklogItemContractConfirm;
import com.mzj.saas.mservice.backlog.entity.BacklogItemContractSign;
import com.mzj.saas.mservice.backlog.repository.BacklogItemContractConfirmRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemContractSignRepository;
import com.mzj.saas.mservice.backlog.repository.BacklogItemRepository;
import com.mzj.saas.mservice.contract.entity.Contract;
import com.mzj.saas.mservice.contract.entity.HouseContractFileRecord;
import com.mzj.saas.mservice.contract.repository.ContractRepository;
import com.mzj.saas.mservice.contract.repository.HouseContractFileRecordRepository;
import com.mzj.saas.mservice.contract.vo.ContractAttachmentVO;
import com.mzj.saas.mservice.contract.vo.ContractContentDetailVO;
import com.mzj.saas.mservice.contract.vo.ContractVO;
import com.mzj.saas.mservice.contract.vo.QysContractInfoVO;
import com.mzj.saas.mservice.department.entity.Department;
import com.mzj.saas.mservice.department.repository.DepartmentRepository;
import com.mzj.saas.mservice.house.entity.House;
import com.mzj.saas.mservice.house.repository.HouseRepository;
import com.mzj.saas.mservice.oss.service.OSSService;
import com.mzj.saas.mservice.qiyuesuo.service.*;
import com.mzj.saas.mservice.qiyuesuo.vo.ContractDraftVO;
import com.mzj.saas.mservice.qiyuesuo.vo.DocumentFileVO;
import com.mzj.saas.mservice.qiyuesuo.vo.ElectronicContractVO;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import com.mzj.saas.redis.RedisService;
import com.qiyuesuo.sdk.v2.bean.Signatory;
import com.qiyuesuo.sdk.v2.bean.Stamper;
import com.qiyuesuo.sdk.v2.bean.Template;
import com.qiyuesuo.sdk.v2.response.SdkResponse;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestHeader;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

/**
 * 契约锁-电子合同app服务
 *
 * @author hp
 */
@Service
public class QiYueSuoAppService {
	private static final Logger log = LoggerFactory.getLogger(QiYueSuoAppService.class);

	@Value("${contract.tmp.dir}")
	private String contractTmpDir;

	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private QiYueSuoTemplateService qiYueSuoTemplateService;
	@Autowired
	private QiYueSuoContractService qiYueSuoContractService;
	@Autowired
	private RedisService redisService;
	@Autowired
	private QiYueSuoSealService qiYueSuoSealService;
	@Autowired
	private QiYueSuoBusinessService qiYueSuoBusinessService;
	@Autowired
	private DepartmentRepository departmentRepository;
	@Autowired
	private AppUserRepository appUserRepository;
	@Autowired
	private ContractRepository contractRepository;
	@Autowired
	private AreaRepository areaRepository;
	@Autowired
	private ContractAppService contractAppService;
	@Autowired
	private QiYueSuoEmployeeService qiYueSuoEmployeeService;
	@Autowired
	private BacklogItemRepository backlogItemRepository;
	@Autowired
	private BacklogItemContractSignRepository backlogItemContractSignRepository;
	@Autowired
	private OssConfig ossConfig;
	@Autowired
	private OSSService ossService;
	@Autowired
	private HouseRepository houseRepository;
	@Autowired
	private BacklogItemContractConfirmRepository backlogItemContractConfirmRepository;
	@Autowired
	private HouseContractFileRecordRepository houseContractFileRecordRepository;

	/**
	 * 获取所有模板
	 *
	 * @return
	 */
	public ResultBean<List<Template>> getTemplates(String accessToken) {

		TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
		if (tokenRedisVo == null) {
			return ResultBean.failedResultOfToken();
		}

		String userId = tokenRedisVo.getId();
		Long enterpriseId = tokenRedisVo.getEnterpriseId();

		log.info("QiYueSuoAppService getTemplates userId={},enterpriseId={}", userId, enterpriseId);

		if (enterpriseId == null) {
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		Optional<Department> departmentOpt = departmentRepository.findById(enterpriseId);

		if (!departmentOpt.isPresent()) {
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		List<Template> templates = qiYueSuoTemplateService.getTemplateList(departmentOpt.get().getName());

		if (templates == null) {
			return ResultBean.failedResultWithMsg("文件模板列表请求失败!");
		}

		return ResultBean.successfulResult(templates);
	}

	/**
	 * 模板预览页面链接
	 *
	 * @param accessToken
	 * @param templateId
	 * @return
	 */
	public ResultBean<String> getTemplatePageurl(Long templateId) {

		log.info("QiYueSuoAppService getTemplatePageurl templateId={}", templateId);

		String pageurl = qiYueSuoTemplateService.getTemplatePageurl(templateId);

		if (pageurl == null) {
			return ResultBean.failedResultWithMsg("模板页面查询请求失败!");
		}
		return ResultBean.successfulResult(pageurl);
	}

	/**
	 * 获取模板详情
	 *
	 * @param templateId
	 * @return
	 */
	public ResultBean<Template> getTemplateDetail(Long templateId) {

		log.info("QiYueSuoAppService getTemplateDetail templateId={}", templateId);

		Template template = qiYueSuoTemplateService.getTemplateDetail(templateId);

		if (template == null) {
			return ResultBean.failedResultWithMsg("获取模板详情请求失败!");
		}

		return ResultBean.successfulResult(template);
	}

	/**
	 * 合同详情
	 *
	 * @param contractId
	 * @return
	 */
	public ResultBean<QysContractInfoVO> getContractDetail(Long contractId) {

		log.info("QiYueSuoAppService getContractDetail contractId={}", contractId);

		com.qiyuesuo.sdk.v2.bean.Contract contract = qiYueSuoContractService.contractDetail(contractId);

		if (contract == null) {

		}

		// contract.getTemplateParams();

		return ResultBean.successfulResult(null);

	}

	/**
	 * 发起合同
	 *
	 * @param accessToken
	 * @param vo
	 * @return
	 *//*
		 * public ResultBean<Object> createContractDraftByTemplate(String
		 * accessToken, QysContractVO vo) {
		 * 
		 * log.info("QiYueSuoAppService createContractDraftByTemplate vo={}",
		 * vo.toString());
		 * 
		 * if (vo.getHouseId() == null || vo.getTemplateId() == null ||
		 * vo.getEarnestMoney() == null ||
		 * StringUtils.isBlank(vo.getStartTime()) ||
		 * StringUtils.isBlank(vo.getEntTime()) || vo.getRentAmount() == null ||
		 * vo.getRentUnitAmount() == null || vo.getPayType() == null ||
		 * vo.getCreateType() == null) { return
		 * ResultBean.failedResultOfParamWithMsg("参数错误"); }
		 * 
		 * if (vo.getCreateType() == 0 && vo.getTemplateId() == null) { return
		 * ResultBean.failedResultOfParamWithMsg("请选择模板"); }
		 * 
		 * if (vo.getCreateType() == 1 && StringUtils.isBlank(vo.getFileBase()))
		 * { return ResultBean.failedResultOfParamWithMsg("请选择文件"); }
		 * 
		 * if (!ContractPayTypeEnum.operate(vo.getPayType())) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 未找到公租房 houseId={}",
		 * vo.getHouseId()); return
		 * ResultBean.failedResultOfParamWithMsg("参数错误"); }
		 * 
		 * TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken); if
		 * (tokenRedisVo == null) { return ResultBean.failedResultOfToken(); }
		 * 
		 * String userId = tokenRedisVo.getId(); Long enterpriseId =
		 * tokenRedisVo.getEnterpriseId();
		 * 
		 * log.info(
		 * "QiYueSuoAppService createContractDraftByTemplate userId={},enterpriseId={}"
		 * , userId, enterpriseId);
		 * 
		 * if (enterpriseId == null) { return
		 * ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查"); }
		 * 
		 * AppUser appuser =
		 * appUserRepository.findByIdOrEnterpriseUserId(userId, userId); if
		 * (appuser == null) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 非法用户 userId={}",
		 * userId); return ResultBean.failedResultWithMsg("非法用户"); }
		 * 
		 * if (appuser.getStatus() != 1) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 您的账号已被禁用 userId={},status={}"
		 * , userId, appuser.getStatus()); return
		 * ResultBean.failedResultWithMsg("您的账号已被禁用"); }
		 * 
		 * Optional<Department> departmentOpt =
		 * departmentRepository.findById(enterpriseId);
		 * 
		 * if (!departmentOpt.isPresent()) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 未找到您当前所在机构/企业 userId={},enterpriseId={}"
		 * , userId, enterpriseId); return
		 * ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查"); }
		 * 
		 * Optional<House> houseOpt = houseRepository.findById(vo.getHouseId());
		 * 
		 * if (!houseOpt.isPresent()) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 未找到公租房 houseId={}",
		 * vo.getHouseId()); return
		 * ResultBean.failedResultOfParamWithMsg("参数错误"); }
		 * 
		 * House house = houseOpt.get();
		 * 
		 * // 查询公租房承租人信息 HouseMatchUser houseMatch =
		 * houseMatchUserRepository.findByHouseIdAndStatus(vo.getHouseId(), 1);
		 * 
		 * if (houseMatch == null) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 公租房承租人信息未找到 houseId={}"
		 * , vo.getHouseId()); return
		 * ResultBean.failedResultOfParamWithMsg("公租房承租人信息未找到,请检查"); }
		 * 
		 * // 资格申请信息 Optional<Eligible> eligibleOpt =
		 * eligibleRepository.findById(houseMatch.getApplyId()); if
		 * (!eligibleOpt.isPresent()) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 公租房承租人信息未找到 houseId={},applyId={}"
		 * , vo.getHouseId(), houseMatch.getApplyId()); return
		 * ResultBean.failedResultOfParamWithMsg("公租房承租人信息未找到,请检查"); }
		 * 
		 * Eligible eligible = eligibleOpt.get();
		 * 
		 * // 模板信息 Template template =
		 * qiYueSuoTemplateService.getTemplateDetail(vo.getTemplateId());
		 * 
		 * if (template == null) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 未找到模板  templateId={}"
		 * , vo.getTemplateId()); return
		 * ResultBean.failedResultOfParamWithMsg("未找到该模板,请重新选择"); }
		 * 
		 * if (!template.getState()) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 模板未启动  templateId={},state={}"
		 * , vo.getTemplateId(), template.getState()); return
		 * ResultBean.failedResultOfParamWithMsg("该模板状态未启动 ,请重新选择"); }
		 * 
		 * Date startTime = DateUtils.convert(vo.getStartTime(),
		 * DateUtils.FORMAT_DATE_8); Date entTime =
		 * DateUtils.convert(vo.getEntTime(), DateUtils.FORMAT_DATE_8);
		 * 
		 * // 业务ID String categoryId =
		 * redisService.getValue(Constant.CATEGORY_ID);
		 * 
		 * ContractDraftVO contractV = new ContractDraftVO();
		 * contractV.setSubject(template.getName()); // contract.setSn(sn);
		 * contractV.setTenantName(departmentOpt.get().getName());
		 * contractV.setEndTime(DateUtils.format(entTime,
		 * DateUtils.FORMAT_DATETIME_14));
		 * contractV.setCategoryId(Long.parseLong(categoryId));
		 * contractV.setParams(vo.getParams());
		 * 
		 * // 2单位申请 if (eligible.getType() == 2) { Optional<Department>
		 * deparEligOpt = departmentRepository.findById(eligible.getOrgId()); if
		 * (!deparEligOpt.isPresent()) { log.error(
		 * "QiYueSuoAppService createContractDraftByTemplate 公租房申请单位未找到   houseId={},orgId={}"
		 * , vo.getHouseId(), eligible.getOrgId()); return
		 * ResultBean.failedResultOfParamWithMsg("公租房申请单位未找到,请检查"); }
		 * contractV.setReceiverTenantName(deparEligOpt.get().getName());
		 * contractV.setReceiverType("COMPANY"); } // 1个人申请 if
		 * (eligible.getType() == 1) {
		 * contractV.setReceiverTenantName(eligible.getName());
		 * contractV.setReceiverType("PERSONAL"); }
		 * contractV.setReceiverName(eligible.getName());
		 * contractV.setReceiverContact(eligible.getMobile());
		 * contractV.setReceiverContactType("MOBILE");
		 * 
		 * contractV.setPartnerTenantName(departmentOpt.get().getName());
		 * contractV.setPartnerName(appuser.getName());
		 * contractV.setPartnerType("COMPANY");
		 * contractV.setPartnerContact(appuser.getPhone());
		 * contractV.setPartnerContactType("MOBILE");
		 * 
		 * // 创建合同草稿 com.qiyuesuo.sdk.v2.bean.Contract contractRes =
		 * qiYueSuoContractService.createContractDraft(contractV); if
		 * (contractRes == null) { return
		 * ResultBean.failedResultOfParamWithMsg("创建合同请求失败,请稍后重试"); }
		 * 
		 * Contract contract = new Contract();
		 * contract.setContractNubmer(String.valueOf(contractRes.getSn()));
		 * contract.setContractTemplateNumber(String.valueOf(vo.getTemplateId())
		 * ); contract.setHouseId(house.getId());
		 * contract.setContractId(String.valueOf(contractRes.getId()));
		 * contract.setLessorName(departmentOpt.get().getName());
		 * contract.setLessorMobile(eligible.getMobile());
		 * 
		 * contract.setMatchUserId(eligible.getMatchUserId());
		 * contract.setLeaseeMobile(appuser.getPhone());
		 * contract.setLeaseeName(eligible.getName());
		 * contract.setCardNumber(eligible.getCardNumber());
		 * contract.setStartTime(startTime); contract.setEntTime(entTime);
		 * contract.setHousingArea(house.getArea());
		 * contract.setRentUnitAmount(DataUtils.doubleToInteger(vo.
		 * getRentUnitAmount().doubleValue()));
		 * contract.setRentAmount(DataUtils.doubleToInteger(vo.getRentAmount().
		 * doubleValue())); contract.setPayType(vo.getPayType());
		 * contract.setEarnestMoney(DataUtils.doubleToInteger(vo.getEarnestMoney
		 * ().doubleValue())); contract.setCityId(house.getCityId());
		 * contract.setDistrictId(house.getDistrictId());
		 * contract.setStreetId(house.getStreetId());
		 * contract.setAddress(house.getAddress());
		 * contract.setRoom(house.getRoom()); contract.setHall(house.getHall());
		 * contract.setToilet(house.getToilet());
		 * contract.setStatus(ContractStatusEnum.DRAFT.getValue());
		 * contract.setReminderTime(DateUtils.getPreDay(entTime, 30));
		 * contract.setOperationId(userId); contract.setOperationTime(new
		 * Date()); contractRepository.save(contract);
		 * 
		 * Long documentId = null;
		 * 
		 * // 创建合同文档 if (vo.getCreateType() == 0) { DocumentTemplateVO dt = new
		 * DocumentTemplateVO(); dt.setContractId(contract.getContractNubmer());
		 * dt.setTemplateId(vo.getTemplateId());
		 * dt.setTemplateParams(vo.getParams());
		 * dt.setTitle(template.getName());
		 * dt.setTenantName(departmentOpt.get().getName()); documentId =
		 * qiYueSuoContractService.documentAddbytemplate(dt); }
		 * 
		 * if (vo.getCreateType() == 1) { DocumentFileVO df = new
		 * DocumentFileVO(); df.setContractId(contract.getContractNubmer());
		 * df.setTenantName(departmentOpt.get().getName());
		 * df.setTitle(template.getName());
		 * df.setFile(Base64Util.base64ToMultipart(vo.getFileBase()));
		 * documentId = qiYueSuoContractService.documentAddbyfile(df, null); }
		 * 
		 * if (documentId == null) { return
		 * ResultBean.failedResultOfParamWithMsg("创建合同请求失败,请稍后重试"); }
		 * contract.setDocumentId(String.valueOf(documentId));
		 * contractRepository.save(contract); // 指定签署位置并发起合同
		 * ElectronicContractVO cv = new ElectronicContractVO();
		 * cv.setContractId(contractRes.getId());
		 * cv.setTenantName(departmentOpt.get().getName()); List<Stamper>
		 * stampers = new ArrayList<>();
		 * 
		 * List<Signatory> signatoryList = contractRes.getSignatories();
		 * 
		 * for (Signatory signa : signatoryList) { Stamper stamper = new
		 * Stamper(); stamper.setDocumentId(documentId);// 合同文档ID if
		 * (signa.getTenantType().equals("COMPANY")) {
		 * stamper.setActionId(signa.getId());// 签署节点ID；公司的签署位置必须（创建合同草稿接口的返回值
		 * stamper.setType("COMPANY"); stamper.setPage(1);
		 * stamper.setOffsetX(0.1); stamper.setOffsetY(0.1); }
		 * 
		 * if (signa.getTenantType().equals("PERSONAL")) {
		 * stamper.setSignatoryId(signa.getId()); stamper.setType("PERSONAL");
		 * stamper.setPage(1); stamper.setOffsetX(0.2); stamper.setOffsetY(0.1);
		 * } stampers.add(stamper); } cv.setStampers(stampers);
		 * SdkResponse<Object> response =
		 * qiYueSuoContractService.sendContract(cv);
		 * 
		 * if (response.getCode() == 0) {
		 * contract.setStatus(ContractStatusEnum.WAITING_SIGNED.getValue());
		 * contractRepository.save(contract); return
		 * ResultBean.successfulResult("合同发起成功,等待签约"); } return
		 * ResultBean.failedResultOfParamWithMsg("创建合同请求失败,请稍后重试"); }
		 */

	/**
	 * 获取签署合同短链接
	 *
	 * @param accessToken
	 * @param vo
	 * @return
	 */
	public ResultBean<Object> contractShorturl(String accessToken, Long contractId) {

		TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
		if (tokenRedisVo == null) {
			return ResultBean.failedResultOfToken();
		}

		String userId = tokenRedisVo.getId();
		Long enterpriseId = tokenRedisVo.getEnterpriseId();

		log.info("QiYueSuoAppService contractShorturl userId={},enterpriseId={}", userId, enterpriseId);

		if (enterpriseId == null) {
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		// Optional<AppUser> appuserOpt = appUserRepository.findById(userId);
		AppUser appuser = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
		if (appuser == null) {
			log.error("QiYueSuoAppService contractShorturl 非法用户 userId={}", userId);
			return ResultBean.failedResultWithMsg("非法用户");
		}

		if (appuser.getStatus() != 1) {
			log.error("QiYueSuoAppService contractShorturl 您的账号已被禁用 userId={},status={}", userId, appuser.getStatus());
			return ResultBean.failedResultWithMsg("您的账号已被禁用");
		}

		Optional<Department> departmentOpt = departmentRepository.findById(enterpriseId);

		if (!departmentOpt.isPresent()) {
			log.error("QiYueSuoAppService contractShorturl 未找到您当前所在机构/企业 userId={},enterpriseId={}", userId,
					enterpriseId);
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		Contract contract = contractRepository.findByContractId(String.valueOf(contractId));

		if (contract == null) {
			return ResultBean.failedResultWithMsg("参数错误");
		}

		String shortUrl = qiYueSuoContractService.contractShorturl(contractId, departmentOpt.get().getName(),
				contract.getLeaseeMobile());

		if (StringUtils.isBlank(shortUrl)) {
			return ResultBean.failedResultWithMsg("生成失败,请稍后重试");
		}

		return ResultBean.successfulResult(shortUrl);
	}

	/**
	 * 下载合同
	 *
	 * @param accessToken
	 * @param contractId
	 */
	public void documentDownload(@RequestHeader String accessToken, Long contractId, HttpServletResponse response)
			throws Exception {

		Contract contract = contractRepository.findByContractId(String.valueOf(contractId));
		if (contract == null) {
			return;
		}

		BufferedOutputStream toClient = null;
		File file = null;
		try {
			file = qiYueSuoContractService.documentDownload(Long.valueOf(contract.getDocumentId()));

			if (file == null) {
				return;
			}

			// 以流的形式下载文件。
			String filename = contract.getCardNumber() + ".pdf";
			InputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
			byte[] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();
			// 清空response
			response.reset();
			// 设置response的Header
			response.addHeader("Content-Disposition",
					"attachment;filename=" + new String(filename.getBytes("utf-8"), "ISO-8859-1"));
			response.addHeader("Content-Length", "" + file.length());
			toClient = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			toClient.write(buffer);
			toClient.flush();
		} catch (Exception e) {

		} finally {
			if (toClient != null) {
				toClient.close();
			}
			if (file != null) {
				file.delete();
			}
		}
	}

	/**
	 * HTML方式生成合同,发起合同
	 *
	 * @param accessToken
	 * @param contractNumber
	 *            合同编号
	 * @param contract
	 *            合同内容(续约)
	 * @param type
	 * @return
	 * @author shun
	 * @date 2021年7月12日
	 */
	@Transactional(rollbackFor = { RuntimeException.class, Exception.class })
	public ResultBean<Object> createContractDraft(String accessToken, String contractNumber, ContractVO contract,
			Integer type) {
		// 续约时更新合同信息
		if (type != null && type == 2) {
			// 调用合同编辑保存接口
			contractAppService.editContract(accessToken, contract);
		}

		Optional<Contract> voOpt = contractRepository.findById(contractNumber);
		if (!voOpt.isPresent()) {
			log.info("生成合同, 合同信息未找到  contractNumber={}", contractNumber);
			return ResultBean.failedResultWithMsg("合同信息未找到");
		}
		Contract vo = voOpt.get();
		log.info("QiYueSuoAppService createContractDraft vo={}", JSON.toJSONString(vo));

		Long count = jdbcTemplate.queryForObject(
				"select count(1) from `saas_house_contract` \n"
						+ "where house_id = ? and match_user_id = ? and status != 0",
				Long.class, vo.getHouseId(), vo.getMatchUserId());
		if (count > 0) {
			return ResultBean.failedResultWithMsg("已有合同记录，不可重复生成");
		}

		// 合同标题
		Optional<Area> area = areaRepository.findById(vo.getCityId());
		if (!area.isPresent()) {
			log.info("生成合同, 合同城市信息有误  contractNumber={}, city={}", contractNumber, vo.getCityId());
			return ResultBean.failedResultWithMsg("合同城市信息有误");
		}

		String subject = area.get().getName() + "公共租赁住房(廉租房)租赁合同";

		// 如果不是草稿状态, 不能进行合同生成操作, 返回错误信息
		if (vo.getStatus() != ContractStatusEnum.DRAFT.getValue()) {
			log.info("生成合同, 合同状态错误  status={}", vo.getStatus());
			return ResultBean.failedResultWithMsg("合同状态错误");
		}

		// 操作用户缓存信息
		TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
		if (tokenRedisVo == null) {
			return ResultBean.failedResultOfToken();
		}

		String userId = tokenRedisVo.getId();
		// 操作用户企业id
		Long enterpriseId = tokenRedisVo.getEnterpriseId();
		log.info("QiYueSuoAppService createContractDraft userId={}, enterpriseId={}", userId, enterpriseId);
		if (enterpriseId == null) {
			log.info("生成合同, 未找到您当前所在机构/企业,请检查,  userId={}, enterpriseId={}", userId, enterpriseId);
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		// 操作用户信息
		AppUser appuser = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
		if (appuser == null) {
			log.info("生成合同, 非法用户 userId={}", userId);
			return ResultBean.failedResultWithMsg("非法用户");
		}

		if (appuser.getStatus() != 1) {
			log.info("生成合同, 您的账号已被禁用 userId={},status={}", userId, appuser.getStatus());
			return ResultBean.failedResultWithMsg("您的账号已被禁用");
		}

		// 操作用户企业信息
		Optional<Department> departmentOpt = departmentRepository.findById(enterpriseId);
		if (!departmentOpt.isPresent()) {
			log.info("生成合同, 未找到您当前所在机构/企业 userId={},enterpriseId={}", userId, enterpriseId);
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		if (vo.getContractTime() == null) {
			vo.setContractTime(new Date());
		}

		// 合同生成电子签章html文件
		File htmlFile = getContractFileHtml(vo, subject);
		if (htmlFile == null) {
			log.info("生成合同, 合同文件生成失败, contractNumber={}", vo.getContractNubmer());
			return ResultBean.failedResultWithMsg("生成合同, 合同文件生成失败,请检查");
		}

		// 本地合同文件路径
		String filePath = contractTmpDir + contractNumber + vo.getHouseId() + ".pdf";
		// 将html文件转换成合同PDF文件
		HtmlToPdfUtils.convert(htmlFile.getPath(), filePath);
		File pdfFile = new File(filePath);
		if (!pdfFile.exists()) {
			log.info("生成合同, 合同生成pdf失败, contractNumber={}", vo.getContractNubmer());
			return ResultBean.failedResultWithMsg("合同生成pdf失败");
		}

		// 业务ID
		// String categoryId = redisService.getValue(Constant.CATEGORY_ID);
		// 根据企业id获取业务id, 默认取列表第一个
		// 查询缓存, ru
		Long categoryId = qiYueSuoBusinessService.getCategoryList(enterpriseId, vo.getLessorName());

		try {
			// 产权单位主管理员
			// User masterUser = homeService.findMainUser(vo.getHouseId());

			// 查询、更新、添加(产权单位)员工信息
			log.info("生成合同, 员工信息, lessorName={}, mobile={}, userName={}", vo.getLessorName(), vo.getLessorMobile(),
					appuser.getName());
			String result = qiYueSuoEmployeeService.validateAddEmployeeExists(vo.getLessorName(), vo.getLessorMobile(),
					appuser.getName());
			if (result != null) {
				return ResultBean.failedResultWithMsg(result);
			}
			/**
			 * 生成契约锁合同草稿
			 */
			ContractDraftVO contractV = new ContractDraftVO();
			contractV.setSubject(subject);
			// 契约锁自动生成, 不传
			// contract.setSn(sn);
			contractV.setTenantName(vo.getLessorName());
			contractV.setEndTime(DateUtils.format(vo.getEntTime(), DateUtils.FORMAT_DATETIME_14));
			// 子公司业务id
			contractV.setCategoryId(categoryId);
			// contractV.setParams(null);

			// 产权单位
			contractV.setPartnerTenantName(vo.getLessorName());
			contractV.setPartnerName(appuser.getName());
			contractV.setPartnerType("COMPANY");
			contractV.setPartnerContact(vo.getLessorMobile());
			contractV.setPartnerContactType("MOBILE");

			// 客户-接收方名称
			contractV.setReceiverTenantName(vo.getLeaseeName());
			// 客户-签署方类型:个人
			contractV.setReceiverType("PERSONAL");
			// 客户-接收方名字
			contractV.setReceiverName(vo.getLeaseeName());
			contractV.setReceiverContact(vo.getLeaseeMobile());
			contractV.setReceiverContactType("MOBILE");

			// 创建合同草稿
			com.qiyuesuo.sdk.v2.bean.Contract contractRes = qiYueSuoContractService.createContractDraft(contractV);
			if (contractRes == null) {
				return ResultBean.failedResultOfParamWithMsg("创建合同请求失败, 请稍后重试");
			}

			/**
			 * 创建合同文档
			 */
			DocumentFileVO df = new DocumentFileVO();
			df.setContractId(String.valueOf(contractRes.getId()));
			df.setTenantName(vo.getLessorName());
			df.setTitle(subject);
			// df.setFile(file);
			df.setFileSuffix("pdf");

			Long documentId = qiYueSuoContractService.documentAddbyfile(df, filePath);
			if (documentId == null) {
				return ResultBean.failedResultOfParamWithMsg("创建合同请求失败, 请稍后重试");
			}
			// 合同文档ID(契约锁)
			vo.setDocumentId(String.valueOf(documentId));
			// 指定签署位置并发起合同
			ElectronicContractVO cv = new ElectronicContractVO();
			cv.setContractId(contractRes.getId());
			cv.setTenantName(vo.getLessorName());
			cv.setStamperRule("MUST_FORBID");
			List<Stamper> stampers = new ArrayList<>();

			List<Signatory> signatoryList = contractRes.getSignatories();

			for (Signatory signa : signatoryList) {
				Stamper stamper = new Stamper();
				stamper.setDocumentId(documentId);// 合同文档ID
				if (signa.getTenantType().equals("COMPANY")) {
					stamper.setActionId(signa.getActions().get(0).getId());// 签署节点ID；公司的签署位置必须（创建合同草稿接口的返回值
					stamper.setType("COMPANY");
					stamper.setPage(1);
					stamper.setKeyword("甲方：");
					// stamper.setOffsetX(0.1);
					// stamper.setOffsetY(0.1);
				}

				if (signa.getTenantType().equals("PERSONAL")) {
					stamper.setSignatoryId(signa.getId());
					stamper.setType("PERSONAL");
					stamper.setPage(1);
					stamper.setKeyword("乙方：");
					// stamper.setOffsetX(0.2);
					// stamper.setOffsetY(0.1);
				}
				stampers.add(stamper);
			}
			cv.setStampers(stampers);
			/**
			 * 指定签署位置并发起合同
			 */
			SdkResponse<Object> responseObj = qiYueSuoContractService.sendContract(cv);
			if (responseObj.getCode() == 0) {
				log.info("合同发起成功");
				/**
				 * 签署公章
				 */
				// 获取子公司印章id
				Long sealId = qiYueSuoSealService.getOrgSeal(enterpriseId, vo.getLessorName());
				if (sealId == null) {
					log.warn("生成合同, 合同印章未找到  enterpriseId={}, lessorName={}", enterpriseId, vo.getLessorName());
					return ResultBean.failedResultWithMsg("合同印章未找到");
				}

				int code = qiYueSuoSealService.contractCompanysign(cv.getContractId(), sealId, cv.getTenantName());
				if (code == 0) {
					/**
					 * 获取合同签订短链接
					 */
					String shortUrl = qiYueSuoSealService.contractShorturl(cv.getContractId(), cv.getTenantName(),
							null);

					// 修改合同状态为：待签约
					vo.setStatus(ContractStatusEnum.WAITING_SIGNED.getValue());
					vo.setShortUrl(shortUrl);
					vo.setContractId(contractRes.getId() == null ? null : String.valueOf(contractRes.getId()));
					// 线上合同模式
					vo.setType(1);
					contractRepository.save(vo);
					// 清理合同草稿
					// deleteTempContract(vo.getHouseId());

					Map<String, String> map = new HashMap<>();
					map.put("msg", "合同发起成功,等待签约");
					map.put("shortUrl", shortUrl);
					map.put("contractNubmer", vo.getContractNubmer());

					// 更新生成合同待办事项状态
					String houseId = vo.getHouseId();
					String matchUserId = vo.getMatchUserId();
					BacklogItem backlogItem = backlogItemRepository.findByHouseIdAndMatchUserIdAndType(houseId,
							matchUserId, BacklogItemTypeEnum.CONTRACT_CREATE.getValue());
					if (backlogItem != null) {
						backlogItem.setBusinessStatus("已生成");
						backlogItem.setHandleStatus(1);
						backlogItem.setHandlerTime(new Date());
						backlogItemRepository.save(backlogItem);
					}

					AppUser appUsers = null;
					if (StringUtils.isNotBlank(matchUserId)){
						appUsers = appUserRepository.findByIdOrEnterpriseUserId(matchUserId, matchUserId);
					}

					// 生成合同待签约待办事项
					BacklogItem signItem = new BacklogItem();
					signItem.setHouseId(houseId);
					signItem.setType(BacklogItemTypeEnum.CONTRACT_SIGN.getValue());
					signItem.setTitle("公租房合同待签约");
					signItem.setBusinessStatus("待签约");
					signItem.setHandleStatus(0);
					signItem.setMatchUserId(matchUserId);
					signItem.setPhone(appUsers != null ? appUsers.getPhone() : null);
					signItem.setShortUrl(shortUrl);
					signItem.setCreateTime(new Date());
					BacklogItem save = backlogItemRepository.save(signItem);

					BacklogItemContractSign sign = new BacklogItemContractSign();
					sign.setBacklogItemId(save.getId());
					sign.setContractNubmer(contractNumber);
					sign.setMatchUserId(matchUserId);
					backlogItemContractSignRepository.save(sign);

					return ResultBean.successfulResult(map);
				} else {
					log.info("生成合同, 公章签署失败, 错误码:{}, 错误信息:{}" + responseObj.getCode() + responseObj.getMessage());
				}
			} else {
				log.info("生成合同, 指定签署位置失败, 错误码:{}, 错误信息:{}", responseObj.getCode(), responseObj.getMessage());
			}
			return ResultBean.failedResultOfParamWithMsg(responseObj.getMessage());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			File file = new File(filePath);
			if (file.exists()) {
				file.delete();
			}

			if (pdfFile.exists()) {
				pdfFile.delete();
			}

			if (htmlFile != null && htmlFile.exists()) {
				htmlFile.delete();
			}

		}
		return ResultBean.failedResultOfParamWithMsg("创建合同请求失败, 请稍后重试");
	}

	/**
	 * 删除失效的草稿合同
	 *
	 * @param contractId
	 * @param houseId
	 * @author shun
	 * @date 2021年6月10日
	 */
	public void deleteTempContract(String houseId) {
		String sql = "delete from saas_house_contract c where c.house_id = ? and c.status = 0";
		jdbcTemplate.update(sql, houseId);
	}

	/**
	 * html文件转pdf
	 *
	 * @param content
	 * @param filePath
	 * @return
	 * @author shun
	 * @date 2021年6月9日
	 */
	public String createPdf1(String content, String filePath) {
		ITextRenderer render = new ITextRenderer();
		ITextFontResolver fontResolver = render.getFontResolver();
		try {
			fontResolver.addFont(getFontPath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			// 解析html生成pdf
			render.setDocumentFromString(content);
			// 解决图片相对路径的问题
			// render.getSharedContext().setBaseURL(LOGO_PATH);

			render.layout();
			render.createPDF(new FileOutputStream(filePath));

			return filePath;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		return null;
	}

	// 字体路径
	private String getFontPath() {
		return System.getProperty("user.dir") + "/src/main/resources/static/contract/SIMHEI.TTF";
	}

	/**
	 * 合同内容转HTML文件
	 *
	 * @param contract
	 * @return
	 * @author shun
	 * @date 2021年6月16日
	 */
	public File getContractFileHtml(Contract contract, String subject) {
		ContractContentDetailVO vo = contractAppService.getContractDetail(contract);
		Map<String, Object> data = new HashMap<>();

		// 合同条款
		data.put("合同条款", vo.getContractTerms().replaceAll("\n", "<br/>"));
		// 合同标题
		data.put("title", subject);
		data.put("租房合同", subject);
		data.put("签约时间", DateUtils.format(contract.getContractTime(), DateUtils.FORMAT_DATETIME_14));
		data.put("签约时间2", DateUtils.format(contract.getContractTime(), DateUtils.FORMAT_DATETIME_14));

		String content = JavaToPdfHtmlFreeMarker.freeMarkerRender(data, "index.html");

		return buildHtml(content, vo, contract.getContractNubmer());
	}

	/**
	 * 合同HTML模板内容补充
	 *
	 * @param htmlStr
	 * @param vo
	 * @return
	 * @author shun
	 * @date 2021年6月16日
	 */
	public File buildHtml(String htmlStr, ContractContentDetailVO vo, String contractNubmer) {
		Document doc = Jsoup.parse(htmlStr);
		Elements srcs = doc.select(".content");
		StringBuffer fieldBuffer = new StringBuffer();
		// 合同字段处理
		for (Map<String, Object> map : vo.getFieldList()) {
			fieldBuffer.append("<div class=\"content_list\">");
			fieldBuffer.append("<div class=\"whiteSpace\">" + map.get("name") + "</div>");
			String name = map.get("name").toString();
			if ("housingArea".equals(name) || "房屋面积".equals(name)) {
				fieldBuffer.append("<div class=\"whiteSpace\">" + map.get("value") + "平方米</div>");
			} else if ("rentUnitAmount".equals(name) || "租金标准".equals(name)) {
				fieldBuffer.append("<div class=\"whiteSpace\">" + map.get("value") + "元/平方米/月</div>");
			} else if ("rentAmount".equals(name) || "租金".equals(name)) {
				fieldBuffer.append("<div class=\"whiteSpace\">" + map.get("value") + "元/月</div>");
			} else if ("earnestMoney".equals(name) || "履约保证金".equals(name)) {
				fieldBuffer.append("<div class=\"whiteSpace\">" + map.get("value") + "元</div>");
			} else if ("payType".equals(name) || "缴纳方式".equals(name)) {
				// 1首次年付，后续按月 2首次年付、后续按季 3首次年付，后续按半年 4首次年付，后续按年
				String value = map.get("value") == null ? "" : map.get("value").toString();
				if ("1".equals(value)) {
					fieldBuffer.append("<div class=\"whiteSpace\">首次年付，后续按月</div>");
				} else if ("2".equals(value)) {
					fieldBuffer.append("<div class=\"whiteSpace\">首次年付、后续按季</div>");
				} else if ("3".equals(value)) {
					fieldBuffer.append("<div class=\"whiteSpace\">首次年付，后续按半年</div>");
				} else if ("4".equals(value)) {
					fieldBuffer.append("<div class=\"whiteSpace\">首次年付，后续按年</div>");
				}
			} else {
				fieldBuffer.append("<div class=\"whiteSpace\">" + map.get("value") + "</div>");
			}
			fieldBuffer.append("</div>");
		}
		srcs.append(fieldBuffer.toString());

		// 合同附件
		StringBuffer attachmentBuffer = new StringBuffer();
		Elements arrt = doc.select(".enclosure");
		int index = 1;
		for (ContractAttachmentVO cvo : vo.getContractAttachmentVO()) {
			attachmentBuffer.append("<div class=\"enclosure_list  mainFontSize\">");
			attachmentBuffer.append("<div class=\"enclosure_id\">" + index + ".</div>");
			attachmentBuffer.append("<div class=\"enclosure_name\">" + cvo.getName() + "</div>");
			attachmentBuffer.append("<div class=\"enclosure_company\">" + cvo.getUnit() + "</div>");
			attachmentBuffer.append("<div class=\"enclosure_situation\">" + cvo.getCurrentSituation() + "</div>");
			attachmentBuffer.append("<div class=\"enclosure_price\">" + cvo.getUnitPrice() + "</div>");
			attachmentBuffer.append("</div>");
			index++;
		}
		arrt.append(attachmentBuffer.toString());

		// 生成文件
		File file = new File(contractTmpDir + contractNubmer + ".html");
		BufferedWriter out = null;
		try {
			if (!file.exists()) {
				file.createNewFile();
			}

			out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
			out.write(doc.toString().replace("doctype", "DOCTYPE"));
			out.newLine();

		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return null;
		} finally {
			if (out != null) {
				try {
					out.flush();
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return file;
	}

	/**
	 * HTML方式生成合同,发起合同
	 *
	 * @param accessToken
	 * @param contractNumber
	 *            合同编号
	 * @param contract
	 *            合同内容(续约)
	 * @param type
	 * @return
	 * @author shun
	 * @date 2021年7月12日
	 */
	@Transactional(rollbackFor = { RuntimeException.class, Exception.class })
	public ResultBean<Object> createOfflineContractDraft(String accessToken, String contractNumber, ContractVO contract,
			Integer type) {
		// 续约时更新合同信息
		if (type != null && type == 2) {
			// 调用合同编辑保存接口
			contractAppService.editContract(accessToken, contract);
		}

		Optional<Contract> voOpt = contractRepository.findById(contractNumber);
		if (!voOpt.isPresent()) {
			log.info("生成合同, 合同信息未找到  contractNumber={}", contractNumber);
			return ResultBean.failedResultWithMsg("合同信息未找到");
		}
		Contract vo = voOpt.get();
		log.info("QiYueSuoAppService createContractDraft vo={}", JSON.toJSONString(vo));

		Long count = jdbcTemplate.queryForObject(
				"select count(1) from `saas_house_contract` \n"
						+ "where house_id = ? and match_user_id = ? and status != 0",
				Long.class, vo.getHouseId(), vo.getMatchUserId());
		if (count > 0) {
			return ResultBean.failedResultWithMsg("已有合同记录，不可重复生成");
		}

		// 合同标题
		Optional<Area> area = areaRepository.findById(vo.getCityId());
		if (!area.isPresent()) {
			log.info("生成合同, 合同城市信息有误  contractNumber={}, city={}", contractNumber, vo.getCityId());
			return ResultBean.failedResultWithMsg("合同城市信息有误");
		}

		String subject = area.get().getName() + "公共租赁住房(廉租房)租赁合同";

		// 如果不是草稿状态, 不能进行合同生成操作, 返回错误信息
		if (vo.getStatus() != ContractStatusEnum.DRAFT.getValue()) {
			log.info("生成合同, 合同状态错误  status={}", vo.getStatus());
			return ResultBean.failedResultWithMsg("合同状态错误");
		}

		// 操作用户缓存信息
		TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
		if (tokenRedisVo == null) {
			return ResultBean.failedResultOfToken();
		}

		String userId = tokenRedisVo.getId();
		// 操作用户企业id
		Long enterpriseId = tokenRedisVo.getEnterpriseId();
		log.info("QiYueSuoAppService createContractDraft userId={}, enterpriseId={}", userId, enterpriseId);
		if (enterpriseId == null) {
			log.info("生成合同, 未找到您当前所在机构/企业,请检查,  userId={}, enterpriseId={}", userId, enterpriseId);
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		// 操作用户信息
		AppUser appuser = appUserRepository.findByIdOrEnterpriseUserId(userId, userId);
		if (appuser == null) {
			log.info("生成合同, 非法用户 userId={}", userId);
			return ResultBean.failedResultWithMsg("非法用户");
		}

		if (appuser.getStatus() != 1) {
			log.info("生成合同, 您的账号已被禁用 userId={},status={}", userId, appuser.getStatus());
			return ResultBean.failedResultWithMsg("您的账号已被禁用");
		}

		// 操作用户企业信息
		Optional<Department> departmentOpt = departmentRepository.findById(enterpriseId);
		if (!departmentOpt.isPresent()) {
			log.info("生成合同, 未找到您当前所在机构/企业 userId={},enterpriseId={}", userId, enterpriseId);
			return ResultBean.failedResultWithMsg("未找到您当前所在机构/企业,请检查");
		}

		if (vo.getContractTime() == null) {
			vo.setContractTime(new Date());
		}
		File pdfFile = null;
		File htmlFile = null;
		try {
			// 合同生成电子签章html文件
			htmlFile = getContractFileHtml(vo, subject);
			if (htmlFile == null) {
				log.info("生成合同, 合同文件生成失败, contractNumber={}", vo.getContractNubmer());
				return ResultBean.failedResultWithMsg("生成合同, 合同文件生成失败,请检查");
			}

			// 本地合同文件路径
			String filePath = contractTmpDir + contractNumber + vo.getHouseId() + ".pdf";
			// 将html文件转换成合同PDF文件
			HtmlToPdfUtils.convert(htmlFile.getPath(), filePath);
			pdfFile = new File(filePath);
			if (!pdfFile.exists()) {
				log.info("生成合同, 合同生成pdf失败, contractNumber={}", vo.getContractNubmer());
				return ResultBean.failedResultWithMsg("合同生成pdf失败");
			}

			// 修改合同状态为：已签约待确认
			vo.setStatus(ContractStatusEnum.WAITING_CONFIRMED.getValue());
			vo.setShortUrl(null);
			vo.setContractId(null);
			// 线下签署合同模式
			vo.setType(2);

			// 上传合同到oss
			String contractDocUrl = ossService.putFile(ossConfig.getOssBucketName(), pdfFile,
					OSSUploadFileTypeEnum.CONTRACT.toString());
			// 合同文件
			vo.setContractDocUrl(contractDocUrl);
			contractRepository.save(vo);

			// 保存合同文件信息
			HouseContractFileRecord record = new HouseContractFileRecord();
			record.setContractNubmer(contract.getContractNubmer());
			record.setContractId(vo.getContractId());
			record.setDocumentId(vo.getDocumentId());
			record.setContractDocUrl(contractDocUrl);
			record.setCreateTime(new Date());
			houseContractFileRecordRepository.save(record);

			// 更新生成合同待办事项状态
			String houseId = vo.getHouseId();
			String matchUserId = vo.getMatchUserId();
			
			BacklogItem oldBacklogItem = backlogItemRepository.findByHouseIdAndMatchUserIdAndType(houseId, matchUserId,
					BacklogItemTypeEnum.CONTRACT_CREATE.getValue());
			if (oldBacklogItem != null) {
				oldBacklogItem.setBusinessStatus("已生成");
				oldBacklogItem.setHandleStatus(1);
				oldBacklogItem.setHandlerTime(new Date());
				backlogItemRepository.save(oldBacklogItem);
			}

			/*// 生成合同待签约待办事项 （线下模式不用待签，只需要做确认操作）
			BacklogItem signItem = new BacklogItem();
			signItem.setHouseId(houseId);
			signItem.setType(BacklogItemTypeEnum.CONTRACT_SIGN.getValue());
			signItem.setTitle("公租房合同待签约");
			signItem.setBusinessStatus("待签约");
			signItem.setHandleStatus(0);
			signItem.setMatchUserId(matchUserId);
			signItem.setShortUrl(null);
			signItem.setCreateTime(new Date());
			BacklogItem save = backlogItemRepository.save(signItem);

			BacklogItemContractSign sign = new BacklogItemContractSign();
			sign.setBacklogItemId(save.getId());
			sign.setContractNubmer(contractNumber);
			sign.setMatchUserId(matchUserId);
			backlogItemContractSignRepository.save(sign);*/
			
			Optional<House> houseOptional = houseRepository.findById(houseId);
            House house = houseOptional.get();
            String leaseeName = contract.getLeaseeName();
            if(StringUtils.isEmpty(leaseeName)){
            	leaseeName = vo.getLeaseeName();
            }

			AppUser user = null;
			if (StringUtils.isNotBlank(matchUserId)){
				 user = appUserRepository.findByIdOrEnterpriseUserId(matchUserId, matchUserId);
			}
			// 生成合同待确认待办事项
			BacklogItem backlogItem = new BacklogItem();
			backlogItem.setHouseId(houseId);
			backlogItem.setOrgId(house.getOrgId());
			backlogItem.setType(BacklogItemTypeEnum.CONTRACT_CONFIRM.getValue());
			backlogItem.setTitle(leaseeName + "申请的公租房合同待确认");
			backlogItem.setContent("合同描述：请尽快确认");
			backlogItem.setBusinessStatus("待确认");
			backlogItem.setHandleStatus(0);
			backlogItem.setMatchUserId(matchUserId);
			if (user != null){
				backlogItem.setPhone(user.getPhone());
			}
			backlogItem.setCreateTime(new Date());
			BacklogItem save = backlogItemRepository.save(backlogItem);

			BacklogItemContractConfirm confirm = new BacklogItemContractConfirm();
			confirm.setBacklogItemId(save.getId());
			confirm.setContractNubmer(contract.getContractNubmer());
			backlogItemContractConfirmRepository.save(confirm);

			Map<String, String> map = new HashMap<>();
			map.put("msg", "合同生成成功,待确认");
			map.put("shortUrl", contractDocUrl);
			map.put("contractNubmer", vo.getContractNubmer());
			return ResultBean.successfulResult(map);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			if (pdfFile != null && pdfFile.exists()) {
				pdfFile.delete();
			}

			if (htmlFile != null && htmlFile.exists()) {
				htmlFile.delete();
			}
		}
		return ResultBean.failedResultOfParamWithMsg("创建合同请求失败, 请稍后重试");
	}

	/**
	 * 合同回调事件处理
	 *
	 * @param signature
	 * @param timestamp
	 * @param content
	 * @return
	 */
	public String contractCallback(String contractId) {
		try {
			log.info("线下合同, 确认签署 , ontractId={}", contractId);

			Contract contract = contractRepository.findByContractId(contractId);
			if (contract == null) {
				log.warn("线下合同, 未找到合同信息   contractId={}", contractId);
				return "success";
			}

			// 已签约待确认
			contract.setStatus(ContractStatusEnum.WAITING_CONFIRMED.getValue());
			contractRepository.save(contract);

			String houseId = contract.getHouseId();
			String matchUserId = contract.getMatchUserId();
			String leaseeName = contract.getLeaseeName();
			Optional<House> houseOptional = houseRepository.findById(houseId);
			House house = houseOptional.get();

			// 更新合同待签约待办事项状态
			BacklogItemContractSign contractSign = backlogItemContractSignRepository
					.findByContractNubmer(contract.getContractNubmer());
			if (contractSign != null) {
				Optional<BacklogItem> backlogItemOpt = backlogItemRepository.findById(contractSign.getBacklogItemId());
				if (backlogItemOpt.isPresent()) {
					BacklogItem item = backlogItemOpt.get();
					item.setBusinessStatus("已签约");
					item.setHandleStatus(1);
					item.setHandlerTime(new Date());
					backlogItemRepository.save(item);
				}
			}

			AppUser user = null;
			if (StringUtils.isNotBlank(matchUserId)){
				 user = appUserRepository.findByIdOrEnterpriseUserId(matchUserId, matchUserId);

			}
			// 生成合同待确认待办事项
			BacklogItem backlogItem = new BacklogItem();
			backlogItem.setHouseId(houseId);
			backlogItem.setOrgId(house.getOrgId());
			backlogItem.setType(BacklogItemTypeEnum.CONTRACT_CONFIRM.getValue());
			backlogItem.setTitle(leaseeName + "申请的公租房合同待确认");
			backlogItem.setContent("合同描述：请尽快确认");
			backlogItem.setBusinessStatus("待确认");
			backlogItem.setHandleStatus(0);
			backlogItem.setMatchUserId(matchUserId);
			if (user != null ){
				backlogItem.setPhone(user.getPhone());
			}
			backlogItem.setCreateTime(new Date());
			BacklogItem save = backlogItemRepository.save(backlogItem);

			BacklogItemContractConfirm confirm = new BacklogItemContractConfirm();
			confirm.setBacklogItemId(save.getId());
			confirm.setContractNubmer(contract.getContractNubmer());
			backlogItemContractConfirmRepository.save(confirm);

			log.info("QiYueSuoService 合同签章成功, 处理已完成");

		} catch (Exception e) {
			log.error("合同事件回调处理异常" + e.getMessage(), e);
		}
		return "success";
	}
	
	/**
	 * 下载合同文件
	 *
	 * @param file
	 * @param response
	 * @author shun
	 * @date 2021年5月31日
	 */
	public void downloadContract(String contractNumber, HttpServletResponse response) {
		Contract contract = contractRepository.findByContractNubmer(String.valueOf(contractNumber));
		if (contract == null) {
			log.error("下载合同文件, 合同不存在, contractNumber={}", contractNumber);
			return;
		}
		File file = ossService.getObjectFile(null, contract.getContractDocUrl());
		try {
			// 读到流中
			InputStream in = new FileInputStream(file);
			response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

			// 导出文件下载
			DownloadUtil downloadUtil = new DownloadUtil();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int len;
			try {
				while ((len = in.read(b)) > 0) {
					bos.write(b, 0, len);
				}

				in.close();
			} catch (IOException e) {
				log.error("Download the document is failed,message:{}", e.getMessage());
			}

			downloadUtil.download(bos, response, file.getName());
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		} finally {
			// 删除原文件
			if (file.exists()) {
				file.delete();
			}
		}
	}
}
